import 'package:family_expense/features/account_user/services/account_group_user_service.dart';
import 'package:family_expense/features/account_user/services/user_service.dart';
import 'package:family_expense/features/account_user/widgets/account_group_user_details.dart';
import 'package:family_expense/features/account_user/widgets/add_account_group_user.dart';
import 'package:family_expense/features/account_user/widgets/user_shared.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

class AccountGroupUserList extends StatefulWidget {
  const AccountGroupUserList({super.key});

  @override
  State<AccountGroupUserList> createState() => _AccountGroupUserListState();
}

class _AccountGroupUserListState extends State<AccountGroupUserList> {
  final int _pageSize = GeneralConfig.listViewPageSize;

  final AccountGroupUserService _accountGroupUserService =
      AccountGroupUserService();

  // Retrieves user data from back server.
  final UserService _userService = UserService();

  // Indicates if display the [CheckListTile] for selection.
  bool _enableItemSelection = false;

  // When user added, updated or removed the last page needs to rebuild the UI.
  bool _dataUpdated = false;

  // Current user info loads from local.
  User? _currentUser;

  // In order to refresh the list after item changes. Including updated, added or removed.
  late PagingListViewLoadController _loadController;

  late SearchDelegate _searchDelegate;

  @override
  void initState() {
    super.initState();

    _getCurrentUser();
    _initSearchDelegate();
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: _onPopInvokedWithResult,
      child: Scaffold(appBar: _buildAppBar(), body: _buildBody()),
    );
  }

  /// Builds app bar.
  PreferredSizeWidget _buildAppBar() {
    return AppBar(
      title: Text(_enableItemSelection ? '选择移除' : '用户列表'),
      actions: <Widget>[
        FutureBuilder<User?>(
          future: AuthStateService.instance.currentUser,
          builder: (context, userSnapshot) {
            if (userSnapshot.data?.isAccountGroupAdmin == true) {
              return IconButton(
                icon: const Icon(Icons.more_horiz),
                onPressed: () {
                  showModalBottomSheet(
                    context: context,
                    builder: (context) => getSelectionBottomSheetContent([
                      ListTile(
                        leading: Icon(MdiIcons.accountPlusOutline),
                        title: const Text('邀请用户'),
                        onTap: () {
                          // Closes opened bottom sheet.
                          NavigatorHelper.pop(context);

                          _openSearch();
                        },
                      ),
                      ListTile(
                        leading: Icon(MdiIcons.accountRemove),
                        title: Text(_enableItemSelection ? '取消选择' : '选择移除'),
                        onTap: () {
                          // Closes opened bottom sheet.
                          NavigatorHelper.pop(context);

                          _toggleItemSelection();
                        },
                      ),
                    ], isHoriz: false),
                  );
                },
              );
            }

            return Container();
          },
        ),
      ],
    );
  }

  /// Builds main body.
  Widget _buildBody() {
    return PagingListView(
      padding: const EdgeInsets.only(top: 10.0),
      pageSize: _pageSize,
      getLoadController: (loadController) => _loadController = loadController,
      retrieveData: (pageIndex) =>
          _userService.queryAccountGroupUsers(_pageSize, pageIndex!),
      itemBuilder: (context, entry, index) => _buildListTile(entry),
    );
  }

  /// Bulids a container for list tile.
  /// This container decorated by border and background color.
  Widget _buildListTileContainer({Widget? child}) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border.all(color: const Color(0xFFEBECF0)),
        borderRadius: const BorderRadius.all(Radius.circular(6.0)),
      ),
      margin: const EdgeInsets.only(left: 12.0, top: 12.0, right: 12.0),
      padding: const EdgeInsets.all(6.0),
      child: child,
    );
  }

  /// Builds to show user full name info.
  Widget _buildUserFullNameInfo(User user) {
    return SizedBox(
      height: 36.0,
      child: Row(
        children: [
          Expanded(
            child: Text(user.fullName!, overflow: TextOverflow.ellipsis),
          ),
          const SizedBox(width: 10.0),
          if (_currentUser?.id == user.id)
            Container(
              margin: const EdgeInsets.only(right: 10.0),
              child: const InfoChip(
                text: '我',
                textColor: Colors.black87,
                backgroundColor: Colors.amber,
              ),
            ),
          if (user.isAccountGroupAdmin!)
            Container(
              margin: const EdgeInsets.only(right: 10.0),
              child: InfoChip(
                text: '管理员',
                textColor: Colors.blue,
                backgroundColor: Colors.blue[50]!,
              ),
            ),
          if (!user.enabled!)
            InfoChip(
              text: '已禁用',
              textColor: Colors.red,
              backgroundColor: Colors.red[50]!,
            ),
        ],
      ),
    );
  }

  /// Builds to show username info.
  Widget _buildUsernameInfo(User user) {
    final style = Theme.of(
      context,
    ).textTheme.titleMedium!.copyWith(fontSize: 14.0, color: Colors.grey);

    return Row(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        const Icon(Icons.phone_android, size: 20.0, color: Colors.grey),
        const SizedBox(width: 6.0),
        Text(user.username!.formatMobilePhoneNumber(), style: style),
      ],
    );
  }

  /// Builds list tile to show user info.
  Widget _buildListTile(User user) {
    return _buildListTileContainer(
      child: ListTile(
        leading: Hero(
          tag: user.id!,
          transitionOnUserGestures: true,
          child: UserAvatorView(user),
        ),
        title: _buildUserFullNameInfo(user),
        subtitle: _buildUsernameInfo(user),
        trailing: _buildListTileTrail(user),
        onTap: () => _gotoDetailView(user),
      ),
    );
  }

  /// Builds delete icon, navigation next icon or a label.
  Widget _buildListTileTrail(User user) {
    Widget trail;

    if (_enableItemSelection) {
      // Cannot delete self or account group creator.
      if (_currentUser?.id != user.id && !user.isAccountGroupCreator!) {
        trail = IconButton(
          icon: const Icon(Icons.clear, color: Colors.red, size: 30.0),
          onPressed: () => _removeUser(user),
        );
      } else {
        trail = Chip(
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.zero),
          ),
          padding: const EdgeInsets.all(0.0),
          label: Text('不可移除', style: Theme.of(context).textTheme.bodySmall),
        );
      }
    } else {
      trail = const ListTileNavigateNextIcon();
    }

    return trail;
  }

  /// Gets current authenticated user.
  Future<void> _getCurrentUser() async {
    final user = await AuthStateService.instance.currentUser;

    if (mounted) {
      setState(() => _currentUser = user!);
    }
  }

  /// Initializes SearchDelegate and saves the delegate for calling its close method later.
  void _initSearchDelegate() {
    _searchDelegate = GeneralSearchDelegate(
      (keyword) =>
          _userService.queryUsersNotInAccountGroup(_pageSize, 0, keyword),
      buildResultItem: (entry) => _buildUserSearchResultListTile(entry),
    );
  }

  /// Starts item selection if [_enableItemSelection] is true. Or completes item selection if [_enableItemSelection] is true.
  ///
  /// It will change the value of [_enableItemSelection] and show related layout.
  void _toggleItemSelection() {
    if (mounted) {
      setState(() => _enableItemSelection = !_enableItemSelection);
    }
  }

  /// Removes user from current accout group.
  void _removeUser(User user) {
    showConfirmDialog(
      context,
      '移除用户 ${user.fullName} (${user.username!.formatMobilePhoneNumber()}) 吗？',
      onConfirm: () async {
        await _accountGroupUserService.remove(user);

        // Reloads the data from server.
        _loadController.reset();

        // The return result to trigger last page to rebuild the UI.
        _dataUpdated = true;
      },
    );
  }

  /// Opens search page for adding new users.
  Future<void> _openSearch() async {
    await showSearch<dynamic>(context: context, delegate: _searchDelegate);
  }

  /// Builds list tile for search result.
  Widget _buildUserSearchResultListTile(User user) {
    return _buildListTileContainer(
      child: ListTile(
        leading: Hero(
          tag: user.id!,
          transitionOnUserGestures: true,
          child: UserAvatorView(user),
        ),
        title: Text(user.fullName!, overflow: TextOverflow.ellipsis),
        subtitle: _buildUsernameInfo(user),
        onTap: () async {
          await NavigatorHelper.push(context, AddAccountGroupUser(user));

          if (mounted) {
            _searchDelegate.close(context, '');
          }
        },
      ),
    );
  }

  /// Goes to detail view.
  Future<void> _gotoDetailView(User user) async {
    final dataUpdated = await NavigatorHelper.push<bool>(
      context,
      AccountGroupUserDetails(user.id!),
    );

    // If the user details is updated we need to refresh the list.
    if (dataUpdated == true) {
      _loadController.reset();

      // We only need to set [_dataUpdated] as true when [dataUpdated] is true.
      //
      // - When user chaged one item then [dataUpdated] is true and [_dataUpdated] is true.
      // - When user goes to edit view and gets back without any change, then [dataUpdated] is false.
      // But we still need to notify last page that some items have been changed.
      //
      // That's why we cannnot set [_dataUpdated] to false when [dataUpdated] is false.
      _dataUpdated = true;
    }
  }

  /// When pops check if need to reset selection mode.
  void _onPopInvokedWithResult(bool didPop, dynamic result) {
    if (didPop) {
      return;
    }

    if (_enableItemSelection) {
      _toggleItemSelection();
    } else {
      NavigatorHelper.pop(context, _dataUpdated);
    }
  }
}
